﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;

namespace SharpShare.Storage.FileSystem {
    internal static class PathUtils {
        private const string FilenameEscapePrefix = "-471b8195-";

        public static FileShare MapToFileShare(this StorageFileAccess shareMode) {
            FileShare fileShare = (FileShare.None | FileShare.Delete);

            switch (shareMode) {
                case StorageFileAccess.Read:
                    fileShare |= FileShare.Read;
                    break;
                case StorageFileAccess.Write:
                    fileShare |= FileShare.Write;
                    break;
                case StorageFileAccess.ReadWrite:
                    fileShare |= FileShare.ReadWrite;
                    break;
            }

            return fileShare;
        }
        public static FileAccess MapToFileAccess(this StorageFileAccess accessMode) {
            FileAccess fileAccess;

            switch (accessMode) {
                case StorageFileAccess.Read:
                    fileAccess = FileAccess.Read;
                    break;
                case StorageFileAccess.Write:
                    fileAccess = FileAccess.Write;
                    break;
                case StorageFileAccess.ReadWrite:
                    fileAccess = FileAccess.ReadWrite;
                    break;
                default:
                    throw new InvalidOperationException();
            }

            return fileAccess;
        }

        public static string EscapeFilename(string name) {
            StringBuilder escaped = new StringBuilder();

            foreach (char c in name) {
                if (Array.IndexOf(System.IO.Path.GetInvalidFileNameChars(), c) > -1) {
                    // Illegal character - escape it.
                    escaped.Append(FilenameEscapePrefix);
                    escaped.Append(((int)c).ToString().PadLeft(3, '0'));
                } else {
                    escaped.Append(c);
                }
            }

            return escaped.ToString();
        }
        public static string UnescapeFilename(string name) {
            string unescaped =
            Regex.Replace(name, FilenameEscapePrefix + "([0-9][0-9][0-9])", match => {
                int charValue = int.Parse(match.Groups[1].Value);
                char c = (char)charValue;
                return c.ToString();
            });
            return unescaped;
        }

        public static string GetParentPath(string path) {
            path = Canonicalize(path);

            int lastSeparator = path.LastIndexOf(System.IO.Path.DirectorySeparatorChar);

            if (lastSeparator == -1) {
                return null;
            }

            path = path.Substring(0, lastSeparator);

            return path;
        }
        public static bool IsEqual(string path1, string path2) {
            return path1.TrimEnd(System.IO.Path.DirectorySeparatorChar).Equals(path2.TrimEnd(System.IO.Path.DirectorySeparatorChar), StringComparison.OrdinalIgnoreCase);
        }
        public static bool IsChild(string path, string checkPath) {
            path = AppendDirectorySeparator(path);
            checkPath = Canonicalize(checkPath);

            if (checkPath.StartsWith(path, StringComparison.OrdinalIgnoreCase)
                && !checkPath.Remove(0, path.Length).Contains(System.IO.Path.DirectorySeparatorChar)) {
                return true;
            }

            return false;
        }
        public static string MakeRelative(string rootPath, string path) {
            rootPath = AppendDirectorySeparator(rootPath);
            if (!path.StartsWith(rootPath, StringComparison.OrdinalIgnoreCase)) {
                return null;
            }

            path = path.Remove(0, rootPath.Length);

            return path;
        }
        public static string Combine(string path1, string path2) {
            return (AppendDirectorySeparator(path1) + Canonicalize(path2));
        }
        public static string AppendDirectorySeparator(string path) {
            return (Canonicalize(path) + System.IO.Path.DirectorySeparatorChar);
        }

        public static string Canonicalize(string path) {
            return path.TrimEnd(System.IO.Path.DirectorySeparatorChar).TrimStart(System.IO.Path.DirectorySeparatorChar);
        }

        public static int GetHashCode(string path) {
            return StringComparer.OrdinalIgnoreCase.GetHashCode(Canonicalize(path));
        }
    }
}
